package top.infopub.tdp.sys.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import javax.annotation.PostConstruct;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import top.infopub.concurrent.ExecutorManager;
import top.infopub.generic.GenericDao;
import top.infopub.generic.GenericServiceImpl;
import top.infopub.model.sys.ParameterGroupDetail;
import top.infopub.model.sys.Parametergroup;
import top.infopub.tdp.domain.DataDictDomain;
import top.infopub.tdp.domain.PageEntity;
import top.infopub.tdp.domain.SysParamDomain;
import top.infopub.tdp.sys.dao.ParameterGroupDetailDao;
import top.infopub.tdp.sys.dao.ParametergroupDao;
import top.infopub.tdp.sys.service.DataDicService;
import top.infopub.tdp.sys.service.ParametergroupService;
import top.infopub.zookeeper.confclient.listener.ConfigurationListener;

/**
 * 系统参数 数据字典 服务
 * @author Awoke
 * @version 2018年9月20日
 * @see ParametergroupServiceImpl
 * @since
 */
@Service("dataDicService")
public class ParametergroupServiceImpl extends GenericServiceImpl<Parametergroup, String> implements
        ParametergroupService, DataDicService, ConfigurationListener {

    private static Logger LOGGER = LoggerFactory.getLogger(ParametergroupServiceImpl.class);

    @Autowired
    private ParametergroupDao parametergroupDao;
    
    @Autowired
    private ParameterGroupDetailDao parameterGroupDetailDao;

    private Map<String, DataDictDomain> caches = null;

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    private static int STEP = 500;

    @Override
    public GenericDao<Parametergroup, String> getDao() {
        return parametergroupDao;
    }

    @PostConstruct
    public void loadDataDict() {
        ExecutorManager.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                int start = 1;
                int end = 0;
                List<SysParamDomain> result = null;
                try {
                    lock.writeLock().lock();
                    caches = new HashMap<String, DataDictDomain>();
                    do {
                        end = start + STEP - 1;
                        result = parametergroupDao.selectParaGroupFetchDetailsAll(new PageEntity(start, end));
                        initCacheInfo(result);
                        start = end + 1;
                    } while (result != null && !result.isEmpty());
                } finally {
                    lock.writeLock().unlock();
                }
            }
        });
    }

    private void initCacheInfo(List<SysParamDomain> sysParams) {
        if (sysParams != null && !sysParams.isEmpty()) {
            for (SysParamDomain dicDomain : sysParams) {
                DataDictDomain _v = caches.get(dicDomain.getGroupNo());
                if (_v == null) {
                    _v = new DataDictDomain();
                    caches.put(dicDomain.getGroupNo(), _v);
                    Parametergroup pgroup = new Parametergroup();
                    pgroup.setId(dicDomain.getGid());
                    pgroup.setBisModify(dicDomain.getIsModify());
                    pgroup.setSgroupName(dicDomain.getGroupName());
                    pgroup.setSgroupNo(dicDomain.getGroupNo());
                    pgroup.setSremark(dicDomain.getGremark());
                    _v.setGroup(pgroup);
                }
                ParameterGroupDetail details = new ParameterGroupDetail();
                details.setId(dicDomain.getDid());
                details.setIsort(dicDomain.getSort());
                details.setSgroupid(_v.getGroup().getId().toString());
                details.setSname(dicDomain.getSname());
                details.setSremark(dicDomain.getDremark());
                details.setSvalue(dicDomain.getSvalue());
                _v.addDataDicDetail(details);
            }
        }
    }

    @Override
    public DataDictDomain selectDataDictInfo(String groupCode) {
        DataDictDomain dest = new DataDictDomain();
        if (caches == null || StringUtils.isEmpty(groupCode)) {
            return dest;
        }
        try {
            lock.readLock().lock();
            DataDictDomain _d = caches.get(groupCode);
            if (_d == null) {
                return dest;
            }
            BeanUtils.copyProperties(dest, _d);
            return dest;
        } catch (Exception e) {
            LOGGER.error("", e);
            return dest;
        } finally {
            lock.readLock().unlock();
        }
    }

    @Override
    public ParameterGroupDetail selectParamGroupDetailInfo(String groupCode, String sname) {
        if (caches == null || StringUtils.isEmpty(groupCode) || StringUtils.isEmpty(sname)) {
            return null;
        }
        try {
            lock.readLock().lock();
            DataDictDomain _vs = caches.get(groupCode);
            if (_vs == null) {
                return null;
            }
            for (ParameterGroupDetail _d : _vs.getDataDicDetails()) {
                if (sname.equalsIgnoreCase(_d.getSname())) {
                    ParameterGroupDetail _dest = new ParameterGroupDetail();
                    BeanUtils.copyProperties(_dest, _d);
                    return _dest;
                }
            }
            return null;
        } catch (Exception e) {
            LOGGER.error("", e);
            return null;
        } finally {
            lock.readLock().unlock();
        }
    }

    @Override
    public void configurationChangedNotice(String keyName,String value) {
        // 重新加载缓存数据 
        if (ZK_NAME.equalsIgnoreCase(keyName)) {
            loadDataDict();
        }
    }

    @Override
    public int queryParametergroupCount(Parametergroup parametergroup) {
        return parametergroupDao.selectCountByExample(parametergroup);
    }

    @Override
    @Transactional
    public void deleteParameterGroup(String[] idArray) {
        parameterGroupDetailDao.batchDeleteByGroupIds(idArray);
        parametergroupDao.batchDeleteByIds(idArray);
    }

    @Override
    public Parametergroup selectByGroupNo(String groupNo) {
        return parametergroupDao.selectByGroupNo(groupNo);
    }

}